<template>
  <Teleport to="body">
    <Transition name="fade">
      <div v-if="modelValue" class="v-popup-mask" @click.self="handleMaskClick">
        <div class="v-popup-container" :style="{ maxWidth: width }">
          <!-- 弹窗头部 -->
          <div class="v-popup-header">
            <div class="v-popup-title">
              <i v-if="icon" :class="['iconfont', icon]"></i>
              <span>{{ title }}</span>
            </div>
            <button class="v-popup-close" @click="handleClose">
              <i class="iconfont icon-close"></i>
            </button>
          </div>

          <!-- 弹窗内容区域 -->
          <div class="v-popup-body">
            <slot></slot>
          </div>

          <!-- 弹窗底部按钮 -->
          <div v-if="showFooter" class="v-popup-footer">
            <button class="v-btn outline" @click="handleClose">取消</button>
            <button
              class="v-btn primary"
              @click="handleConfirm"
              :disabled="confirmLoading"
            >
              <i v-if="confirmLoading" class="iconfont icon-loading spin"></i>
              {{ confirmText }}
            </button>
          </div>
        </div>
      </div>
    </Transition>
  </Teleport>
</template>

<script>
export default {
  name: "vPopup",
  props: {
    modelValue: {
      type: Boolean,
      default: false,
    },
    title: {
      type: String,
      default: "提示",
    },
    width: {
      type: String,
      default: "600px",
    },
    icon: {
      type: String,
      default: "",
    },
    showFooter: {
      type: Boolean,
      default: true,
    },
    closeOnClickMask: {
      type: Boolean,
      default: true,
    },
    confirmText: {
      type: String,
      default: "确认",
    },
    asyncConfirm: {
      type: Boolean,
      default: false,
    }
  },
  emits: ['update:modelValue', 'confirm', 'close'],
  data() {
    return {
      confirmLoading: false,
    };
  },
  methods: {
    handleClose() {
      this.$emit('update:modelValue', false);
      this.$emit('close');
    },
    async handleConfirm() {
      if (this.asyncConfirm) {
        this.confirmLoading = true;
        try {
          await this.$emit('confirm');
          this.handleClose();
        } finally {
          this.confirmLoading = false;
        }
      } else {
        this.$emit('confirm');
        this.handleClose();
      }
    },
    handleMaskClick() {
      if (this.closeOnClickMask) {
        this.handleClose();
      }
    },
  },
};
</script>

<style scoped lang="less">
.v-popup-mask {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: rgba(0, 0, 0, 0.5);
  z-index: 1000;
  display: flex;
  justify-content: center;
  align-items: center;
}

.v-popup-container {
  background-color: white;
  border-radius: 8px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
  width: 100%;
  max-width: 600px;
  max-height: 80vh;
  display: flex;
  flex-direction: column;
}

.v-popup-header {
  padding: 16px 24px;
  border-bottom: 1px solid #f0f0f0;
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.v-popup-title {
  font-size: 16px;
  font-weight: 600;
  display: flex;
  align-items: center;
  
  .iconfont {
    margin-right: 8px;
    color: var(--v-theme);
  }
}

.v-popup-close {
  background: none;
  border: none;
  color: #999;
  cursor: pointer;
  font-size: 16px;
  
  &:hover {
    color: var(--v-danger);
  }
}

.v-popup-body {
  padding: 24px;
  overflow-y: auto;
  flex: 1;
}

.v-popup-footer {
  padding: 16px 24px;
  border-top: 1px solid #f0f0f0;
  display: flex;
  justify-content: flex-end;
  gap: 12px;
  
  .v-btn {
    min-width: 80px;
    height: 36px;
    padding: 0 16px;
    font-size: 14px;
    border-radius: 4px;
    
    &.outline {
      background-color: white;
      border: 1px solid #d9d9d9;
      color: #333;
      
      &:hover {
        border-color: var(--v-theme);
        color: var(--v-theme);
      }
    }
    
    &.primary {
      background-color: var(--v-theme);
      color: white;
      border: none;
      opacity: .85;
      &:hover {
        background-color: var(--v-theme);
        opacity: 1;
      }
      
      &[disabled] {
        background-color: #ccc;
        cursor: not-allowed;
      }
    }
  }
}

/* 加载动画 */
.spin {
  animation: spin 1s linear infinite;
}

@keyframes spin {
  from { transform: rotate(0deg); }
  to { transform: rotate(360deg); }
}

/* 过渡动画 */
.fade-enter-active,
.fade-leave-active {
  transition: opacity 0.3s;
}

.fade-enter-from,
.fade-leave-to {
  opacity: 0;
}
</style>